﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;

namespace ifunction
{
    /// <summary>
    /// Extension class for http operations.
    /// </summary>
    public static partial class HttpExtensions
    {
        /// <summary>
        /// Checks the null object.
        /// </summary>
        /// <param name="anyObject">Any object.</param>
        /// <param name="objectIdentity">The object identity.</param>
        /// <exception cref="System.NullReferenceException"></exception>
        public static void CheckNullObject(this object anyObject, string objectIdentity)
        {
            if (anyObject == null)
            {
                throw new NullReferenceException(objectIdentity);
            }
        }

        #region Read response

        /// <summary>
        /// Gets text content from WebResponse by default encoding.
        /// </summary>
        /// <param name="httpRequest">The <c>HttpWebRequest</c> instance.</param>
        /// <returns>The content string.</returns>
        public static string ReadTextFromResponse(this HttpWebRequest httpRequest, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }

            if (httpRequest != null)
            {
                var response = httpRequest.GetResponse();
                return response.ReadAsText(encoding);
            }

            return string.Empty;
        }

        /// <summary>
        /// Gets text content from WebResponse by specified encoding.
        /// </summary>
        /// <param name="webResponse">The WebResponse instance.</param>
        /// <param name="encoding">The encoding.</param>
        /// <returns>The content string.</returns>
        public static string ReadAsText(this WebResponse webResponse, Encoding encoding = null)
        {
            string result = string.Empty;

            if (webResponse != null)
            {
                try
                {
                    using (Stream responseStream = webResponse.GetResponseStream())
                    {
                        if (encoding == null)
                        {
                            encoding = Encoding.UTF8;
                        }
                        StreamReader streamReader = new StreamReader(responseStream, encoding);
                        result = streamReader.ReadToEnd();
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("ReadAsText", ex);
                }
                finally
                {
                    webResponse.Close();
                }
            }

            return result;
        }

        #endregion

        #region Fill Data On HttpWebRequest

        /// <summary>
        /// Fills the file data on HTTP web request.
        /// </summary>
        /// <param name="httpWebRequest">The HTTP web request.</param>
        /// <param name="dataMappings">The data mappings.</param>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="paramName">Name of the param.</param>
        /// <param name="contentType">Type of the content.</param>
        public static void FillFileData(this HttpWebRequest httpWebRequest, Dictionary<string, string> dataMappings, string fileName, string paramName, string contentType)
        {
            string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
            byte[] boundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

            if (httpWebRequest != null)
            {
                httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
                httpWebRequest.Method = "POST";
                httpWebRequest.KeepAlive = true;

                Stream stream = httpWebRequest.GetRequestStream();

                string formDataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
                foreach (string key in dataMappings.Keys)
                {
                    stream.Write(boundaryBytes, 0, boundaryBytes.Length);
                    string formItem = string.Format(formDataTemplate, key, dataMappings[key]);
                    byte[] formItemBytes = System.Text.Encoding.UTF8.GetBytes(formItem);
                    stream.Write(formItemBytes, 0, formItemBytes.Length);
                }
                stream.Write(boundaryBytes, 0, boundaryBytes.Length);

                if (!string.IsNullOrWhiteSpace(fileName) && File.Exists(fileName))
                {
                    string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
                    string header = string.Format(headerTemplate, paramName, fileName, contentType);
                    byte[] headerBytes = System.Text.Encoding.UTF8.GetBytes(header);
                    stream.Write(headerBytes, 0, headerBytes.Length);

                    FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                    byte[] buffer = new byte[4096];
                    int bytesRead = 0;
                    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                    {
                        stream.Write(buffer, 0, bytesRead);
                    }
                    fileStream.Close();
                }

                byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
                stream.Write(trailer, 0, trailer.Length);
                stream.Close();
            }
        }

        /// <summary>
        /// Fills post data on HttpWebRequest.
        /// </summary>
        /// <param name="httpWebRequest">The HttpWebRequest instance.</param>
        /// <param name="method">The method.</param>
        public static void FillData(this HttpWebRequest httpWebRequest, string method, Dictionary<string, string> dataMappings)
        {
            if (httpWebRequest != null)
            {
                StringBuilder sb = new StringBuilder();
                if (dataMappings != null)
                {
                    foreach (string key in dataMappings.Keys)
                    {
                        string value = string.Empty;
                        if (dataMappings[key] != null)
                        {
                            value = dataMappings[key];
                        }
                        sb.Append(key + "=" + value.Trim() + "&");
                    }

                }
                if (sb.Length > 0)
                {
                    sb.Remove(sb.Length - 1, 1);
                }
                ASCIIEncoding encoding = new ASCIIEncoding();
                byte[] data = encoding.GetBytes(sb.ToString());

                httpWebRequest.Method = method;
                httpWebRequest.ContentType = "application/x-www-form-urlencoded";
                httpWebRequest.ContentLength = data.Length;
                Stream stream = httpWebRequest.GetRequestStream();
                stream.Write(data, 0, data.Length);
                stream.Close();
            }
        }

        /// <summary>
        /// Fills the data on HTTP web request.
        /// </summary>
        /// <param name="httpWebRequest">The HTTP web request.</param>
        /// <param name="method">The method.</param>
        /// <param name="data">The data.</param>
        public static void FillData(this HttpWebRequest httpWebRequest, string method, byte[] data)
        {
            if (httpWebRequest != null && data != null)
            {
                httpWebRequest.Method = method;
                httpWebRequest.ContentType = "text/xml; charset=utf-8";
                httpWebRequest.ContentLength = data.Length;
                Stream dataStream = httpWebRequest.GetRequestStream();
                dataStream.Write(data, 0, data.Length);
                dataStream.Close();
            }
        }

        /// <summary>
        /// Fills the data on HTTP web request.
        /// </summary>
        /// <param name="httpWebRequest">The HTTP web request.</param>
        /// <param name="method">The method.</param>
        /// <param name="data">The data.</param>
        public static void FillData(this HttpWebRequest httpWebRequest, string method, string data)
        {
            FillData(httpWebRequest, method, data, null);
        }

        /// <summary>
        /// Fills the data on HTTP web request.
        /// </summary>
        /// <param name="httpWebRequest">The HTTP web request.</param>
        /// <param name="method">The method.</param>
        /// <param name="data">The data.</param>
        /// <param name="encodingToByte">The encoding to byte.</param>
        public static void FillData(this HttpWebRequest httpWebRequest, string method, string data, Encoding encodingToByte)
        {
            byte[] byteArray = null;

            if (!string.IsNullOrWhiteSpace(data))
            {
                if (encodingToByte == null)
                {
                    encodingToByte = Encoding.UTF8;
                }
                byteArray = encodingToByte.GetBytes(data);
            }

            FillData(httpWebRequest, method, byteArray);
        }

        #endregion
    }
}
